Language Reference / Namespaces


Namespaces overview

  1. broadest definition => encapsulating(封裝) items
  2. Example: the file foo.txt can exist in both directory /home/greg and in /home/other, but two copies of foo.txt cannot co-exist in the same directory
  3. Support Version: (PHP 5 >= 5.3.0, PHP 7)
  4. Name collisions(衝突) between code you create, and
    1. internal PHP classes
    2. functions
    3. constants
    4. third-party classes - functions/constants
  5. Ability to alias(別名) (or shorten) Extra_Long_Names designed to alleviate(和緩) the first problem, improving readability of source code

Examples: Namespace syntax example

<?php
namespace my\name; // see "Defining Namespaces" section

class MyClass {}
function myfunction() {}
const MYCONST = 1;

$a = new MyClass;
$c = new \my\name\MyClass; // see "Global Space" section

$a = strlen('hi'); // see "Using namespaces: fallback to global
                   // function/constant" section

$d = namespace\MYCONST; // see "namespace operator and __NAMESPACE__
                        // constant" section
$d = __NAMESPACE__ . '\MYCONST';
echo constant($d); // see "Namespaces and dynamic language features" section
?>

Note:

  1. Namespace names PHP and php => not be used in the userspace code => reserved for internal language

Defining namespaces

  1. types of code are affected by namespaces
    1. classes (including abstracts and traits)
    2. interfaces
    3. functions
    4. constants
  2. A file containing a namespace must declare the namespace at the top of the file before any other code - with one exception: the declare keyword

Examples: no non-PHP code may precede a namespace declaration

<html>
<?php
namespace MyProject; // fatal error - namespace must be the first statement in the script
?>

Note:

  1. the same namespace may be defined in multiple files, allowing splitting up of a namespace's contents across the filesystem

Defining multiple namespaces in the same file

Examples: Declaring multiple namespaces, simple combination syntax(not recommended)

<?php
namespace MyProject;

const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }

namespace AnotherProject;

const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }
?>

This syntax is not recommended for combining namespaces into a single file => recommended to use the alternate bracketed syntax

Examples: Declaring multiple namespaces, simple combination syntax(recommended)

<?php
namespace MyProject {

const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }
}

namespace AnotherProject {

const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }
}
?>

discouraged as a coding practice to combine multiple namespaces into the same file

To combine global non-namespaced code with namespaced code, Global code should be encased in a namespace statement with no namespace

Examples: Declaring multiple namespaces and unnamespaced code

<?php
namespace MyProject {

const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }
}

namespace { // global code
session_start();
$a = MyProject\connect();
echo MyProject\Connection::start();
}

// or
declare(encoding='UTF-8');
namespace MyProject {

const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }
}

namespace { // global code
session_start();
$a = MyProject\connect();
echo MyProject\Connection::start();
}
?>

No PHP code may exist outside of the namespace brackets except for an opening declare statement


Using namespaces: Basics

  1. Unqualified name
    1. Examples:
      1. $a = new foo()
      2. foo::staticmethod()
  2. Qualified name
    1. $a = new subnamespace\foo()
    2. subnamespace\foo::staticmethod();
  3. Fully qualified name
    1. $a = new \currentnamespace\foo()
    2. \currentnamespace\foo::staticmethod()

Examples:

<?php
namespace FOO\Bar\subnamespace;

const FOO = 1;
function foo(){}
class foo {
static function staticmethod(){}
}

namespace Foo\Bar;
const FOO = 2;
function foo(){ echo "Foo\Bar\\foo";}
class foo {
static function staticmethod(){
echo "Foo\Bar\\foo::staticmethod()";
}
}

/* Unqualified name */
foo(); // Foo\Bar\foo
echo "\n";
foo::staticmethod(); // Foo\Bar\foo::staticmethod()
echo "\n";

/* Qualified name */
echo subnamespace\FOO; // 1
echo "\n";

/* Fully qualified name */
\FOO\Bar\foo(); // Foo\Bar\foo
echo "\n";
\Foo\Bar\foo::staticmethod(); // Foo\Bar\foo::staticmethod()
echo "\n";
echo \Foo\Bar\FOO; // 2

Examples: Accessing global classes, functions and constants from within a namespace

<?php
namespace Foo;

function strlen() {}
const INI_ALL = 3;
class Exception {}

$a = \strlen('hi'); // calls global function strlen
$b = \INI_ALL; // accesses global constant INI_ALL
$c = new \Exception('error'); // instantiates global class Exception
?>

Namespaces and dynamic language features

Examples: Dynamically accessing elements

<?php
class classname
{
    function __construct()
    {
        echo __METHOD__,"\n";
    }
}
function funcname()
{
    echo __FUNCTION__,"\n";
}
const constname = "global";

$a = 'classname';
$obj = new $a; // prints classname::__construct
$b = 'funcname';
$b(); // prints funcname
echo constant('constname'), "\n"; // prints global
?>

Examples: Dynamically accessing namespaced elements

<?php
namespace namespacename;
class classname
{
    function __construct()
    {
        echo __METHOD__,"\n";
    }
}
function funcname()
{
    echo __FUNCTION__,"\n";
}
const constname = "namespaced";

/* note that if using double quotes, "\\namespacename\\classname" must be used */
$a = '\namespacename\classname';
$obj = new $a; // prints namespacename\classname::__construct
$a = 'namespacename\classname';
$obj = new $a; // also prints namespacename\classname::__construct
$b = 'namespacename\funcname';
$b(); // prints namespacename\funcname
$b = '\namespacename\funcname';
$b(); // also prints namespacename\funcname
echo constant('\namespacename\constname'), "\n"; // prints namespaced
echo constant('namespacename\constname'), "\n"; // also prints namespaced
?>

namespace keyword and __NAMESPACE__ constant

PHP supports two ways of abstractly accessing elements within the current namespace

  1. __NAMESPACE__ magic constant
  2. namespace keyword

Examples:

<?php
namespace MyProject;

echo '"', __NAMESPACE__, '"'; // outputs "MyProject"
?>

Examples: __NAMESPACE__ example, global code

<?php
echo '"', __NAMESPACE__, '"'; // outputs ""
?>

Examples: using __NAMESPACE__ for dynamic name construction

<?php
namespace MyProject;

function get($classname)
{
    $a = __NAMESPACE__ . '\\' . $classname;
    return new $a;
}
?>

Using namespaces: Aliasing/Importing

The ability to refer to an external fully qualified name with an alias, or importing, is an important feature of namespaces. This is similar to the ability of unix-based filesystems to create symbolic links to a file or to a directory.

All versions of PHP that support namespaces support three kinds of

aliasing or importing:

  1. aliasing a class name
  2. aliasing an interface name
  3. aliasing a namespace name.

PHP 5.6+ also allows aliasing or importing

  1. function
  2. constant names.

aliasing is accomplished with the use operator

Examples: importing/aliasing with the use operator

<?php
namespace foo;
use My\Full\Classname as Another;

// this is the same as use My\Full\NSname as NSname
use My\Full\NSname;

// importing a global class
use ArrayObject;

// importing a function (PHP 5.6+)
use function My\Full\functionName;

// aliasing a function (PHP 5.6+)
use function My\Full\functionName as func;

// importing a constant (PHP 5.6+)
use const My\Full\CONSTANT;

$obj = new namespace\Another; // instantiates object of class foo\Another
$obj = new Another; // instantiates object of class My\Full\Classname
NSname\subns\func(); // calls function My\Full\NSname\subns\func
$a = new ArrayObject(array(1)); // instantiates object of class ArrayObject
// without the "use ArrayObject" we would instantiate an object of class foo\ArrayObject
func(); // calls function My\Full\functionName
echo CONSTANT; // echoes the value of My\Full\CONSTANT
?>

Examples: importing/aliasing with the use operator, multiple use statements combined

<?php
use My\Full\Classname as Another, My\Full\NSname;

$obj = new Another; // instantiates object of class My\Full\Classname
NSname\subns\func(); // calls function My\Full\NSname\subns\func
?>

Examples: Importing and dynamic names

<?php
use My\Full\Classname as Another, My\Full\NSname;

$obj = new Another; // instantiates object of class My\Full\Classname
$a = 'Another';
$obj = new $a;      // instantiates object of class Another
?>

Examples: Importing and fully qualified names

<?php
use My\Full\Classname as Another, My\Full\NSname;

$obj = new Another; // instantiates object of class My\Full\Classname
$obj = new \Another; // instantiates object of class Another
$obj = new Another\thing; // instantiates object of class My\Full\Classname\thing
$obj = new \Another\thing; // instantiates object of class Another\thing
?>

Scoping rules for importing

The use keyword must be declared in the

  1. outermost scope of a file (the global scope)
  2. inside namespace declarations

This is because the importing is done at compile time and not runtime

Examples: Illegal importing rule

<?php
namespace Languages;

function toGreenlandic()
{
    use Languages\Danish;

    // ...
}
?>

Group use declarations

Examples:

<?php

// Pre PHP 7 code
use some\namespace\ClassA;
use some\namespace\ClassB;
use some\namespace\ClassC as C;

use function some\namespace\fn_a;
use function some\namespace\fn_b;
use function some\namespace\fn_c;

use const some\namespace\ConstA;
use const some\namespace\ConstB;
use const some\namespace\ConstC;

// PHP 7+ code
use some\namespace\{ClassA, ClassB, ClassC as C};
use function some\namespace\{fn_a, fn_b, fn_c};
use const some\namespace\{ConstA, ConstB, ConstC};

Note:

  1. importing only affects unqualified and qualified names. Fully qualified names are absolute, and unaffected by imports
  2. Importing rules are per file basis, meaning included files will NOT inherit the parent file's importing rules.

Global space

Without any namespace definition, all class and function definitions are placed into the global space

Examples: Using global space specification

<?php
namespace A\B\C;

/* This function is A\B\C\fopen */
function fopen() { 
     /* ... */
     $f = \fopen(...); // call global fopen
     return $f;
} 
?>

Using namespaces: fallback to global function/constant

when PHP encounters an unqualified Name in a class name, function or constant context, it resolves these with different priorities. Class names always resolve to the current namespace name

Examples: Accessing global classes inside a namespace

<?php
namespace A\B\C;
class Exception extends \Exception {}

$a = new Exception('hi'); // $a is an object of class A\B\C\Exception
$b = new \Exception('hi'); // $b is an object of class Exception

$c = new ArrayObject; // fatal error, class A\B\C\ArrayObject not found
?>

Examples: global functions/constants fallback inside a namespace

<?php
namespace A\B\C;

const E_ERROR = 45;
function strlen($str)
{
    return \strlen($str) - 1;
}

echo E_ERROR, "\n"; // prints "45"
echo INI_ALL, "\n"; // prints "7" - falls back to global INI_ALL

echo strlen('hi'), "\n"; // prints "1"
if (is_array('hi')) { // prints "is not array"
    echo "is array\n";
} else {
    echo "is not array\n";
}
?>

Name resolution rules

Namespace name definitions

  1. Unqualified name => This is an identifier without a namespace separator => such as foo
  2. Qualified name => This is an identifier with a namespace separator => such as Foo\Bar

  3. Fully qualified name => This is an identifier with a namespace separator that begins with a namespace separator => \Foo\Bar

  4. Relative name => This is an identifier starting with namespace, such as namespace\Foo\Bar

Names are resolved following these resolution rules:

  1. Fully qualified names always resolve to the name without leading namespace separator. For instance \A\B => A\B
  2. Relative names always resolve to the name with namespace replaced by the current namespace. If the name occurs in the global namespace, the namespace\ prefix is stripped. For example namespace\A inside namespace X\Y resolves to X\Y\A. The same name inside the global namespace resolves to A.
  3. For qualified names the first segment of the name is translated according to the current class/namespace import table. For example, if the namespace A\B\C is imported as C, the name C\D\E is translated to A\B\C\D\E.
  4. For qualified names, if no import rule applies, the current namespace is prepended to the name. For example, the name C\D\E inside namespace A\B, resolves to A\B\C\D\E.
  5. For unqualified names, the name is translated according to the current import table for the respective symbol type. This means that class-like names are translated according to the class/namespace import table, function names according to the function import table and constants according to the constant import table. For example, after use A\B\C; a usage such as new C() resolves to the name A\B\C(). Similarly, after use function A\B\fn; a usage such as fn() resolves to the name A\B\fn
  6. For unqualified names, if no import rule applies and the name refers to a class-like symbol, the current namespace is prepended. For example new C() inside namespace A\B resolves to name A\B\C.
  7. For unqualified names, if no import rule applies and the name refers to a function or constant and the code is outside the global namespace, the name is resolved at runtime. Assuming the code is in namespace A\B, here is how a call to function foo() is resolved: It looks for a function from the current namespace: A\B\foo(). It tries to find and call the global function foo().

Examples: Name resolutions illustrated

results matching ""

    No results matching ""